/*
 * CityBuilderGame.cpp
 *
 *  Created on: Jun 29, 2010
 *      Author: Ry
 */

#include <vector>
#include <GL/glew.h>
#include <event/events.h>
#include <event/SDLPlayerController.h>
#include <event/SDLEventCallback.h>
#include <gui/gl/GLButton.h>
#include <gui/gl/GLGUI.h>
#include <gui/sdl/SDLGUIEventHandler.h>

#include "CityBuilderGame.h"
#include "TerrainGrid.h"
#include "BuilderController.h"
#include "SimpleTUIOEventHandler.h"
#include "TUIOGUIEventHandler.h"

using namespace std;
using namespace TUIO;

CityBuilderGame::CityBuilderGame(): Game() {
	// We shall call it..."City Builder"
	window->setTitle("City Builder");

	SimpleWorld *simpleWorld = new SimpleWorld();
	world = simpleWorld;

	// Position the player somewhere
	Object *player = simpleWorld->getCamera()->getParent();
	player->positionAt(0, 10, 50);
	player->setRotation(0, 180, 0);

	gui = new GLGUI();

	ShaderProgram *program = resources->newShaderProgram();
	program->addVertexShader("resources/shaders/multitexture.vert");
	program->addFragmentShader("resources/shaders/multitexture.frag");
	program->build();
	program->use();

	ShaderProgram *guishader = resources->newShaderProgram();
	guishader->addVertexShader("resources/shaders/sdlgui.vert");
	guishader->addFragmentShader("resources/shaders/sdlgui.frag");
	guishader->build();

//	// Create a grid to build the city on
//	TerrainGrid *grid = new TerrainGrid(100, 100);
//	grid->positionAt(0, 0, 0);
//	world->addObject(grid);

	// Load building meshes
	vector<Mesh*> buildingMeshes;
	buildingMeshes.push_back(resources->loadMesh("resources/meshes/com_office.dwarfmesh", program));
	buildingMeshes.push_back(resources->loadMesh("resources/meshes/ind_power.dwarfmesh", program));

	buildingSelectWindow = (GLWindow*)gui->add(new GLWindow(guishader));
	buildingSelectWindow->positionAt(10, 10);
	buildingSelectWindow->resize(110, 215);

	// Create the office button
	GLButton *officeButton = (GLButton*)buildingSelectWindow->add(new GLButton(guishader));
	officeButton->setBackgroundTexture(resources->loadTexture("resources/textures/Button-Office.png", false));
	officeButton->resize(100, 100);
	officeButton->setDrawBorder(false);
	officeButton->setBackgroundColor(RGBA(0xcccccc, 1.0));

	// Create the power button
	GLButton *powerButton = (GLButton*)buildingSelectWindow->add(new GLButton(guishader));
	powerButton->setBackgroundTexture(resources->loadTexture("resources/textures/Button-Power.png", false));
	powerButton->resize(100, 100);
	powerButton->setDrawBorder(false);
	powerButton->setBackgroundColor(RGBA(0xcccccc, 1.0));

	// Create event dispatchers
	sdlEventDispatcher = new SDLEventDispatcher();
	tuioEventDispatcher = new TUIOEventDispatcher();
	eventDispatchers.push_back(sdlEventDispatcher);
	eventDispatchers.push_back(tuioEventDispatcher);

	// Create event handlers
	sdlEventDispatcher->add(new SDLGUIEventHandler(gui, window));
	//sdlEventDispatcher->add(new BuilderController(player, world, buildingMeshes));
	sdlEventDispatcher->add(new SDLEventCallback<CityBuilderGame>(this, &CityBuilderGame::eventCallback));
	tuioEventDispatcher->add(new SimpleTUIOEventHandler(gui, window, guishader, &cursors, player, world, buildingMeshes));
	tuioEventDispatcher->add(new TUIOGUIEventHandler(gui, window, &cursors));
}
void CityBuilderGame::configureOpenGL() {
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

	glMatrixMode(GL_TEXTURE);
	glLoadIdentity();
	glScalef(1.0f, -1.0f, 1.0f);
}

void CityBuilderGame::eventCallback(SDL_Event event, float dts) {
	if(event.type == SDL_USEREVENT && (event.user.code == FULLSCREENED_EVENT || event.user.code == WINDOWED_EVENT)) {
		resources->rebuildShaderPrograms();
		resources->updateTextures();
		resources->updateMeshes();

		WindowResolution res = *(WindowResolution*)event.user.data1;
		world->getCamera()->setAspect((float)res.width / (float) (res.height > 0 ? res.height : 1));

		SDL_Event mouseEvent;
		SDL_PeepEvents(&mouseEvent, 1, SDL_GETEVENT, SDL_MOUSEMOTIONMASK);
		configureOpenGL();
	}
	if (event.type == SDL_VIDEORESIZE) {
		window->resize(event.resize.w, event.resize.h);

		resources->rebuildShaderPrograms();
		resources->updateTextures();
		resources->updateMeshes();

		configureOpenGL();

		float aspect = (float)event.resize.w / (float) (event.resize.h > 0 ? event.resize.h : 1);
		world->getCamera()->setAspect(aspect);
	}
	if (event.type == SDL_KEYUP) {
		if (event.key.keysym.sym == SDLK_F10) {
			window->toggleFullScreen();
		}
		if (event.key.keysym.sym == SDLK_ESCAPE) {
			runLevel = EXIT;
		}
	}
	if (event.type == SDL_QUIT) {
		runLevel = EXIT;
	}
}

CityBuilderGame::~CityBuilderGame() {
	delete sdlEventDispatcher;
	delete tuioEventDispatcher;
}
